package lee.vioson.ebook.viewmodels

import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import lee.vioson.composecommon.base.mvi.BaseViewModel
import lee.vioson.composecommon.base.mvi.Reducer
import lee.vioson.composecommon.base.mvi.UiEvent
import lee.vioson.composecommon.base.mvi.UiState
import lee.vioson.ebook.data.AppContainer
import lee.vioson.remotedata.bean.BookData
import lee.vioson.remotedata.bean.Chapter
import lee.vioson.remotedata.bean.ChapterInfo

/**
 *Author:viosonlee
 *Date:2023/6/15
 *DESCRIPTION:
 */
class ReadViewModel(
    private val appContainer: AppContainer,
    chapter: Chapter,
    private val book: BookData,
) : AppViewModel<ReadViewModel.State, ReadViewModel.Event>(appContainer.appEvent) {

    private val reducer = SubReducer(
        State(
            chapter = chapter,
            isCollection = book.isCollection
        )
    )

    fun addBookReadHistory() = appContainer.homeRepository.addBooksHistory(book.bookInfo)
        .catch { handleException(it) }
        .launchIn(viewModelScope)

    fun chapterInfoList(chapter: Chapter) =
        appContainer.bookRepository.chapterDetail(appContainer.uniqueId, chapter.id)
            .catch { handleException(it) }
            .onStart { showLoading() }
            .onCompletion { dismissLoading() }
            .onEach { sendEvent(Event.OnChapterInfoListChange(it)) }
            .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), listOf())
            .launchIn(viewModelScope)

    fun addCollection(addFavorite: Boolean) =
        appContainer.bookRepository.changeCollection(appContainer.uniqueId, addFavorite, book.bookInfo.id)
            .catch { handleException(it) }
            .onStart { sendEvent(Event.OnCollectionLoadingChange(true)) }
            .onCompletion { sendEvent(Event.OnCollectionLoadingChange(false)) }
            .onEach { if (it) sendEvent(Event.OnCollectionChange(isCollection = addFavorite)) }
            .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false)
            .launchIn(viewModelScope)

    override val state: StateFlow<State>
        get() = reducer.state

    override fun sendEvent(event: Event) {
        reducer.sendEvent(event)
    }

    fun onPrevious(chapterList: List<Chapter>, chapter: Chapter) {
        val index = chapterList.indexOf(chapter)
        if (index < 1) return
        val newIndex = index - 1
        sendEvent(Event.OnChapterChange(chapterList[newIndex]))
    }

    fun onNext(chapterList: List<Chapter>, chapter: Chapter) {
        val index = chapterList.indexOf(chapter)
        if (index < 0 || index >= chapterList.lastIndex) return
        val newIndex = index + 1
        sendEvent(Event.OnChapterChange(chapterList[newIndex]))
    }

    private class SubReducer(initialState: State) :
        Reducer<State, Event>(initialState) {
        override fun reduce(oldState: State, event: Event) {
            when (event) {
                is Event.OnCollectionChange -> setState(oldState.copy(isCollection = event.isCollection))
                is Event.OnCollectionLoadingChange -> setState(oldState.copy(collectionLoading = event.collectionLoading))
                is Event.OnToggleController -> setState(oldState.copy(showController = event.showController))
                is Event.OnToggleChapterList -> setState(oldState.copy(showList = event.showList))
                is Event.OnChapterChange -> setState(oldState.copy(chapter = event.chapter))
                is Event.OnChapterInfoListChange -> setState(oldState.copy(chapterInfoList = event.chapterInfoList))
            }
        }
    }


    sealed class Event : UiEvent {
        data class OnCollectionChange(val isCollection: Boolean) : Event()
        data class OnCollectionLoadingChange(val collectionLoading: Boolean) : Event()
        data class OnToggleController(val showController: Boolean) : Event()
        data class OnToggleChapterList(val showList: Boolean) : Event()
        data class OnChapterChange(val chapter: Chapter) : Event()
        data class OnChapterInfoListChange(val chapterInfoList: List<ChapterInfo>) : Event()
    }

    data class State(
        val chapter: Chapter,
        val showController: Boolean = false,
        val showList: Boolean = false,
        val isCollection: Boolean = false,
        val collectionLoading: Boolean = false,
        val chapterInfoList: List<ChapterInfo> = emptyList()
    ) : UiState
}

